/*!
 * \file test_boost_mapping_file.cpp
 * \project WonderTrader
 * 
 * \brief BoostMappingFile内存映射文件测试套件
 * 
 * \details 测试BoostMappingFile类的各种功能，包括：
 *          - 文件映射和取消映射
 *          - 不同访问模式的支持
 *          - 内存地址和大小获取
 *          - 文件同步操作
 *          - 错误处理和异常安全
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "../../src/Share/BoostMappingFile.hpp"
#include "../../src/Share/BoostFile.hpp"
#include <fstream>
#include <thread>
#include <vector>
#include <chrono>
#include <cstring>
#include <random>
#include <cstdio>

/*!
 * \brief BoostMappingFile测试套件
 * 
 * \details 全面测试BoostMappingFile的功能，包括：
 *          - 基本的文件映射操作
 *          - 不同访问模式测试
 *          - 内存操作和数据一致性
 *          - 错误处理验证
 */
class BoostMappingFileTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 测试前准备
        test_file = "test_mapping_file.dat";
        test_content = "Hello, BoostMappingFile Test! This is test content for memory mapping.";
        
        // 创建测试文件
        createTestFile(test_file, test_content);
    }
    
    void TearDown() override {
        // 测试后清理
        std::vector<std::string> test_files = {
            test_file,
            "test_mapping_large.dat",
            "test_mapping_readonly.dat",
            "test_mapping_sync.dat",
            "test_mapping_concurrent.dat"
        };
        
        for (const auto& file : test_files) {
            if (BoostFile::exists(file.c_str())) {
                std::remove(file.c_str());
            }
        }
    }
    
    void createTestFile(const std::string& filename, const std::string& content) {
        std::ofstream file(filename, std::ios::binary);
        if (file.is_open()) {
            file.write(content.c_str(), content.size());
            file.close();
        }
    }
    
    std::string test_file;
    std::string test_content;
};

// ========== 基本功能测试 ==========

/*!
 * \brief 测试基本文件映射
 */
TEST_F(BoostMappingFileTest, TestBasicMapping) {
    BoostMappingFile mapping;
    
    // 测试映射文件
    EXPECT_TRUE(mapping.map(test_file.c_str()));
    EXPECT_TRUE(mapping.valid());
    
    // 验证映射信息
    EXPECT_NE(mapping.addr(), nullptr);
    EXPECT_EQ(mapping.size(), test_content.size());
    EXPECT_STREQ(mapping.filename(), test_file.c_str());
    
    // 验证映射内容
    if (mapping.addr() != nullptr && mapping.size() > 0) {
        char* mapped_data = static_cast<char*>(mapping.addr());
        std::string mapped_content(mapped_data, mapping.size());
        EXPECT_EQ(mapped_content, test_content);
    }
    
    // 测试关闭映射
    mapping.close();
    EXPECT_FALSE(mapping.valid());
    EXPECT_EQ(mapping.addr(), nullptr);
    EXPECT_EQ(mapping.size(), 0);
}

/*!
 * \brief 测试映射不存在的文件
 */
TEST_F(BoostMappingFileTest, TestMappingNonexistentFile) {
    BoostMappingFile mapping;
    
    // 尝试映射不存在的文件
    EXPECT_FALSE(mapping.map("nonexistent_file.dat"));
    EXPECT_FALSE(mapping.valid());
    EXPECT_EQ(mapping.addr(), nullptr);
    EXPECT_EQ(mapping.size(), 0);
}

/*!
 * \brief 测试空文件映射
 */
TEST_F(BoostMappingFileTest, TestEmptyFileMapping) {
    std::string empty_file = "test_mapping_empty.dat";
    
    // 创建空文件
    std::ofstream file(empty_file);
    file.close();
    
    BoostMappingFile mapping;
    
    // 尝试映射空文件，可能会抛出异常
    try {
        bool result = mapping.map(empty_file.c_str());
        
        if (result) {
            // 如果映射成功，验证大小为0
            EXPECT_EQ(mapping.size(), 0);
            mapping.close();
        } else {
            // 如果映射失败，这也是可接受的
            EXPECT_FALSE(mapping.valid());
        }
    } catch (const std::exception& e) {
        // 空文件映射可能会抛出异常，这是可接受的
        // 注意：在某些情况下，映射可能仍然有效但抛出异常
        std::cout << "空文件映射异常（预期行为）: " << e.what() << std::endl;
    }
    
    std::remove(empty_file.c_str());
}

/*!
 * \brief 测试重复映射
 */
TEST_F(BoostMappingFileTest, TestRepeatedMapping) {
    BoostMappingFile mapping;
    
    // 第一次映射
    EXPECT_TRUE(mapping.map(test_file.c_str()));
    EXPECT_TRUE(mapping.valid());
    size_t first_size = mapping.size();
    
    // 第二次映射同一文件（应该先关闭之前的映射）
    mapping.close();
    EXPECT_TRUE(mapping.map(test_file.c_str()));
    EXPECT_TRUE(mapping.valid());
    
    // 验证映射信息
    EXPECT_NE(mapping.addr(), nullptr);
    EXPECT_EQ(mapping.size(), first_size);
    
    mapping.close();
}

/*!
 * \brief 测试析构函数自动清理
 */
TEST_F(BoostMappingFileTest, TestDestructorCleanup) {
    {
        BoostMappingFile mapping;
        EXPECT_TRUE(mapping.map(test_file.c_str()));
        EXPECT_NE(mapping.addr(), nullptr);
        EXPECT_GT(mapping.size(), 0);
        
        // 映射对象在作用域结束时自动析构
    }
    
    // 验证析构后资源已释放（通过创建新映射验证）
    BoostMappingFile new_mapping;
    EXPECT_TRUE(new_mapping.map(test_file.c_str()));
    EXPECT_TRUE(new_mapping.valid());
    new_mapping.close();
}

// ========== 错误处理测试 ==========

/*!
 * \brief 测试无效操作
 */
TEST_F(BoostMappingFileTest, TestInvalidOperations) {
    BoostMappingFile mapping;
    
    // 在未映射状态下的操作
    EXPECT_FALSE(mapping.valid());
    EXPECT_EQ(mapping.addr(), nullptr);
    EXPECT_EQ(mapping.size(), 0);
    
    // 多次关闭应该安全
    mapping.close();
    mapping.close();
    
    // 同步未映射的文件应该安全
    mapping.sync();
}

/*!
 * \brief 测试文件名获取
 */
TEST_F(BoostMappingFileTest, TestFilenameRetrieval) {
    BoostMappingFile mapping;
    
    // 映射后应该能获取正确的文件名
    EXPECT_TRUE(mapping.map(test_file.c_str()));
    EXPECT_STREQ(mapping.filename(), test_file.c_str());
    
    mapping.close();
}

// ========== 同步操作测试 ==========

/*!
 * \brief 测试文件同步
 */
TEST_F(BoostMappingFileTest, TestFileSync) {
    BoostMappingFile mapping;
    ASSERT_TRUE(mapping.map(test_file.c_str()));
    
    // 执行同步操作（应该不会崩溃）
    mapping.sync();
    
    // 关闭映射
    mapping.close();
}

// ========== 并发访问测试 ==========

/*!
 * \brief 测试多线程并发映射
 */
TEST_F(BoostMappingFileTest, TestConcurrentMapping) {
    std::string concurrent_file = "test_mapping_concurrent.dat";
    std::string content = "Concurrent access test content";
    createTestFile(concurrent_file, content);
    
    const int num_threads = 4;
    std::vector<std::thread> threads;
    std::atomic<int> success_count(0);
    
    // 启动多个线程同时映射同一文件
    for (int i = 0; i < num_threads; i++) {
        threads.emplace_back([&concurrent_file, &content, &success_count, i]() {
            BoostMappingFile mapping;
            
            if (mapping.map(concurrent_file.c_str())) {
                // 验证映射内容
                if (mapping.addr() != nullptr && mapping.size() > 0) {
                    char* data = static_cast<char*>(mapping.addr());
                    std::string mapped_content(data, mapping.size());
                    
                    if (mapped_content == content) {
                        success_count++;
                    }
                }
                
                // 模拟一些工作
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
                
                mapping.close();
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证所有线程都成功
    EXPECT_EQ(success_count.load(), num_threads);
    
    std::remove(concurrent_file.c_str());
} 